<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  

  
  <title>Hexo</title>
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  <meta name="description" content="[TOC] Docker学习之路使用Docker镜像获取镜像直接从Docker Hub镜像源下载镜像： docker [image] pull NAME[:TAG] 示例： docker pull ubuntu:18.04 docker pull ubuntu NAME是镜像仓库名称，TAG是镜像的标签。通常情况下，描述一个镜像需要“名称+标签”。   一般来说，不加TAG表示拉取最新版镜像。镜像">
<meta property="og:type" content="article">
<meta property="og:title" content="Hexo">
<meta property="og:url" content="http://example.com/2021/10/13/docker/index.html">
<meta property="og:site_name" content="Hexo">
<meta property="og:description" content="[TOC] Docker学习之路使用Docker镜像获取镜像直接从Docker Hub镜像源下载镜像： docker [image] pull NAME[:TAG] 示例： docker pull ubuntu:18.04 docker pull ubuntu NAME是镜像仓库名称，TAG是镜像的标签。通常情况下，描述一个镜像需要“名称+标签”。   一般来说，不加TAG表示拉取最新版镜像。镜像">
<meta property="og:locale" content="en_US">
<meta property="article:published_time" content="2021-10-13T12:08:45.470Z">
<meta property="article:modified_time" content="2021-10-13T12:14:35.812Z">
<meta property="article:author" content="John Doe">
<meta name="twitter:card" content="summary">
  
    <link rel="alternate" href="/atom.xml" title="Hexo" type="application/atom+xml">
  
  
    <link rel="icon" href="/favicon.png">
  
  
    <link href="//fonts.googleapis.com/css?family=Source+Code+Pro" rel="stylesheet" type="text/css">
  
  
<link rel="stylesheet" href="/css/style.css">

<meta name="generator" content="Hexo 5.4.0"></head>

<body>
  <div id="container">
    <div id="wrap">
      <header id="header">
  <div id="banner"></div>
  <div id="header-outer" class="outer">
    <div id="header-title" class="inner">
      <h1 id="logo-wrap">
        <a href="/" id="logo">Hexo</a>
      </h1>
      
    </div>
    <div id="header-inner" class="inner">
      <nav id="main-nav">
        <a id="main-nav-toggle" class="nav-icon"></a>
        
          <a class="main-nav-link" href="/">Home</a>
        
          <a class="main-nav-link" href="/archives">Archives</a>
        
      </nav>
      <nav id="sub-nav">
        
          <a id="nav-rss-link" class="nav-icon" href="/atom.xml" title="RSS Feed"></a>
        
        <a id="nav-search-btn" class="nav-icon" title="Search"></a>
      </nav>
      <div id="search-form-wrap">
        <form action="//google.com/search" method="get" accept-charset="UTF-8" class="search-form"><input type="search" name="q" class="search-form-input" placeholder="Search"><button type="submit" class="search-form-submit">&#xF002;</button><input type="hidden" name="sitesearch" value="http://example.com"></form>
      </div>
    </div>
  </div>
</header>
      <div class="outer">
        <section id="main"><article id="post-docker" class="article article-type-post" itemscope itemprop="blogPost">
  <div class="article-meta">
    <a href="/2021/10/13/docker/" class="article-date">
  <time datetime="2021-10-13T12:08:45.470Z" itemprop="datePublished">2021-10-13</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
    <div class="article-entry" itemprop="articleBody">
      
        <p>[TOC]</p>
<h1 id="Docker学习之路"><a href="#Docker学习之路" class="headerlink" title="Docker学习之路"></a>Docker学习之路</h1><h2 id="使用Docker镜像"><a href="#使用Docker镜像" class="headerlink" title="使用Docker镜像"></a>使用Docker镜像</h2><h3 id="获取镜像"><a href="#获取镜像" class="headerlink" title="获取镜像"></a>获取镜像</h3><p>直接从Docker Hub镜像源下载镜像：</p>
<p><code>docker [image] pull NAME[:TAG]</code></p>
<p>示例：</p>
<p><code>docker pull ubuntu:18.04</code></p>
<p><code>docker pull ubuntu</code></p>
<p>NAME是镜像仓库名称，TAG是镜像的标签。通常情况下，描述一个镜像需要“名称+标签”。</p>
<blockquote>
<p> 一般来说，不加TAG表示拉取最新版镜像。镜像的latest标签意味着该镜像的内容会跟踪最新版本的变更而变化，内容不稳定。因此，从稳定上考虑，不要在生产环境中忽略镜像的标签信息或者使用默认的latest标记的镜像。</p>
</blockquote>
<p><code>docker pull ubuntu:18.04</code>表示从默认的注册服务器Docker Hub Registry中的ubuntu仓库下载标记为18.04的镜像。</p>
<p>若从非官方的仓库下载，则需要指定完成的仓库地址。</p>
<p><code>docker pull hub.c.163.com/public/ubuntu:18.04</code></p>
<h3 id="查看镜像信息"><a href="#查看镜像信息" class="headerlink" title="查看镜像信息"></a>查看镜像信息</h3><p>使用<code>docker images</code> 或者<code>docker image ls</code>命令查看已经下载安装的镜像。</p>
<p>使用tag命令添加镜像标签：</p>
<p><code>docker tag ubuntu:latest myubuntu:latest</code> </p>
<blockquote>
<p>myubuntu:latest和ubuntu:latest的ID是完全一致的，它们指向了同一个镜像文件，只是别名不同。</p>
</blockquote>
<p>使用<code>docker inspect NAME:TAG</code>命令可以获取该镜像的详细信息</p>
<p>使用<code>docker history NAME:TAG</code>命令列出各层的创建信息，附加<code>--no-trunc</code>显示截断的信息。</p>
<p>使用<code>docker search [option] keyword</code>来搜索Docker Hub官方仓库中的镜像。</p>
<h3 id="删除和清理镜像"><a href="#删除和清理镜像" class="headerlink" title="删除和清理镜像"></a>删除和清理镜像</h3><p><code>docker rmi</code>和<code>docker image rm</code>命令可以删除镜像，使用<code>docker rmi -f</code>强制删除镜像。可以加标签或者镜像ID。</p>
<p>使用<code>docker ps -a</code>查看本机存在的容器。</p>
<blockquote>
<p>通常并不推荐使用<code>-f</code>强制删除一个存在容器依赖的镜像，正确的做法是先删除该镜像的所有容器，再来删除镜像。</p>
<p>Docker镜像和Docker容器</p>
<p>Docker镜像类似于虚拟机镜像，镜像是创建Docker容器的基础。</p>
<p>Docker容器类似于一个轻量级的沙箱，Docker利用容器来运行和隔离应用。容器是从镜像创建的应用运行实例，容器可以启动、开始、停止、删除，这些容器都是彼此相互隔离、互不相见的。</p>
<p>可以把容器看作一个简易的Linux系统环境(包括root用户权限、进程空间、用户空间和网络空间等)以及运行在其中的应用程序打包而成的盒子。</p>
</blockquote>
<p>使用<code>docker image prune</code>清理系统中遗留的一些临时镜像文件，以及一些没有被使用的镜像，可以附加<code>-a</code>删除所有无用的镜像，不仅仅是临时镜像，附加<code>-f</code>强制删除镜像，不进行提示，附加<code>-filter</code>只清理符合给定过滤器的镜像。</p>
<h3 id="创建镜像"><a href="#创建镜像" class="headerlink" title="创建镜像"></a>创建镜像</h3><p>创建镜像的三种方法：基于已有的镜像的容器创建、基于本地模板导入、基于Dockerfile创建。</p>
<ul>
<li><p>基于已有容器创建</p>
<p>使用<code>docker commit</code>命令</p>
<ul>
<li><code>-a,--author=&quot;&quot;</code>：作者信息</li>
<li><code>-c,--change=[]</code>:提交时执行Dockerfile指令</li>
<li><code>-m,--message=&quot;&quot;</code>：提交消息</li>
<li><code>-p,--pause=true</code>:提交时暂停容器运行</li>
</ul>
</li>
<li><p>基于本地模板导入</p>
<p>使用<code>docker import</code>命令，命令格式为：</p>
<p><code>docker [image] import [OPTIONS] file|URL|-[REPOSITORY[:TAG]] </code></p>
<p>要直接导入一个镜像，可以使用OpenVZ提供的模板来创建，或者其他已导出的镜像模板来创建。OpenVZ模板的下载地址为:<code>https://wiki.openvz.org/Download/template/precreated</code></p>
</li>
<li><p>基于Dockerfile创建(待补充)</p>
<p>基于Dockerfile创建是最常见的方式。</p>
</li>
</ul>
<h3 id="存出和载入镜像"><a href="#存出和载入镜像" class="headerlink" title="存出和载入镜像"></a>存出和载入镜像</h3><p>使用<code>docker [image] save</code>和<code>docker [image]load</code>命令来存出和载入镜像。</p>
<ul>
<li><p>存出镜像</p>
<p>如果要导出镜像到本地文件，可以使用<code>docker [image] save</code>命令。</p>
<p>示例：</p>
<p><code>docker save -o ubuntu_18.04.tar ubuntu:18.04</code></p>
</li>
<li><p>载入镜像</p>
<p>使用<code>docker [image] load</code>将导出的tar文件再导入到本地镜像库。</p>
<p>示例：</p>
<p><code>docker load -i ubuntu_18.04.tar</code></p>
<p><code>docker load &lt; ubuntu_18.04.tar</code></p>
</li>
</ul>
<h3 id="上传镜像"><a href="#上传镜像" class="headerlink" title="上传镜像"></a>上传镜像</h3><p>  命令格式为：</p>
<p><code>docker [image] push NAME[:TAG] |[REGISTRY_HOST[:REGISTRY_PORT]/]NAME[:TAG]</code></p>
<p>示例：</p>
<p><code>docker tag test:latest user/test:latest</code></p>
<p><code>docker push user/test:latest</code></p>
<h2 id="操作Docker容器"><a href="#操作Docker容器" class="headerlink" title="操作Docker容器"></a>操作Docker容器</h2><h3 id="创建容器"><a href="#创建容器" class="headerlink" title="创建容器"></a>创建容器</h3><ul>
<li><p>新建容器</p>
<p>使用<code>docker [container] create</code>命令新建一个容器。</p>
<p>示例：</p>
<p><code>docker create -it ubuntu:latest</code></p>
</li>
<li><p>启动容器</p>
<p>使用<code>docker [container] start</code>命令来启动一个已经创建的容器。</p>
</li>
<li><p>新建并启动容器</p>
<p>命令<code>docker [container] run</code>等价于先执行<code>docker [container] create</code>，再执行<code>docker [container] start</code>命令。</p>
<p>当使用<code>docker [container] run</code>命令来创建并启动容器时，Docker在后台运行的标准操作包括：</p>
<ol>
<li><p>检查本地是否存在指定的镜像，不存在就从公有仓库下载</p>
</li>
<li><p>利用镜像创建一个容器 ，并启动该容器</p>
</li>
<li><p>分配一个文件系统给容器 ，并在只读的镜像层外面挂载一层可读写层</p>
</li>
<li><p>从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中去</p>
</li>
<li><p>从网桥的地址池配置一个IP地址给容器</p>
</li>
<li><p>执行用户指定的应用程序</p>
</li>
<li><p>执行完毕后容器被自动终止</p>
</li>
</ol>
<p>示例：</p>
<p><code>docker run -it ubuntu:18.04 /bin/bash</code></p>
<blockquote>
<p>其中，附加<code>-t</code>命令让Docker分配一个伪终端（pseudo-tty）并绑定到容器的标准输入上，附加<code>-i</code>命令让容器的标准输入保持打开。</p>
</blockquote>
<p>使用<code>docker container wait CONTAINER [CONTAINER...]</code>子命令来等待容器退出，并打印退出返回结果。</p>
<p>常见错误代码：</p>
<ul>
<li><p>125：Docker daemon执行出错，例如执行了不支持的Docker命令参数</p>
</li>
<li><p>126：所指定的命令无法执行，例如权限出错</p>
</li>
<li><p>127：容器内命令无法找到</p>
</li>
</ul>
</li>
<li><p>守护态运行</p>
<p>可以附加<code>-d</code>参数让Docker容器在后台以守护态（Daemonized）形式运行。</p>
<p>示例：</p>
<p><code>docker run -d ubuntu /bin/sh -c &quot;while true; do echo hello world; sleep 1; done&quot;</code></p>
</li>
<li><p>查看容器输出</p>
<p>使用<code>docker [container] logs</code>命令获取容器的输出信息。</p>
<p>示例：</p>
<p><code>docker logs f5198677b810</code></p>
<h2 id="停止容器"><a href="#停止容器" class="headerlink" title="停止容器"></a>停止容器</h2><ul>
<li><p>暂停容器</p>
<p>使用<code>docker [container] pause CONTAINER [CONTAINER...]</code>命令来暂停一个运行中的容器。</p>
<p>示例：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">docker run --name <span class="built_in">test</span>  --rm -it ubuntu bash</span><br><span class="line">docker pause <span class="built_in">test</span></span><br></pre></td></tr></table></figure>

<p>处于paused状态的容器，使用<code>docker [container] unpause CONTAINER [CONTAINER...]</code>命令来恢复到运行状态。</p>
</li>
</ul>
</li>
<li><p>终止容器</p>
<p>使用<code>docker [container] stop</code>来终止一个运行中的容器，命令格式为：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker [container] stop [-t|--time[=10]] [CONTAINER...]</span><br></pre></td></tr></table></figure>

<p>使用<code>docker [container] kill</code>直接发送SIGKILL信号来强行终止容器。</p>
<p><code>docker [container] restart</code>命令会先将一个运行态的容器先终止，然后再重新启动。</p>
</li>
</ul>
<h3 id="进入容器"><a href="#进入容器" class="headerlink" title="进入容器"></a>进入容器</h3><p>使用<code>-d</code>参数后容器会进入后台运行，无法直接看到容器中的信息，也无法进行操作。</p>
<ul>
<li><p>attach命令</p>
<p>attach是Docker自带的命令，命令格式为：</p>
</li>
</ul>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker [container] attach [--detach-keys[=[]]] [--no-stdin] [--sig-proxy[=<span class="literal">true</span>]] CONTAINER</span><br></pre></td></tr></table></figure>

<p><code>--detach-keys[=[]]</code>:指定退出attach模式的快捷键序列，默认是<code>CTRL-p和CTRL-q</code></p>
<p><code>--no-stdin=true|false</code>:是否关闭标准输入，默认总是打开</p>
<p><code>--sig-proxy=true|false</code> :是否代理收到的系统信号给应用进程，默认为打开</p>
<p>示例：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">$ docker run -itd ubuntu</span><br><span class="line">0dfbff61afc417def487e0b80b21766108bda3e43239e5a09a130faa4ff7b742</span><br><span class="line">$ docker ps</span><br><span class="line">CONTAINER ID   IMAGE     COMMAND       CREATED         STATUS         PORTS     NAMES</span><br><span class="line">0dfbff61afc4   ubuntu    <span class="string">&quot;/bin/bash&quot;</span>   9 seconds ago   Up 8 seconds             naughty_goodall</span><br><span class="line">$ docker attach naughty_goodall</span><br><span class="line">root@0dfbff61afc4:/<span class="comment">#</span></span><br></pre></td></tr></table></figure>

<blockquote>
<p>当多个窗口同时attach到同一个容器时，所有窗口都会同步显示；当某个窗口因命令阻塞时，其他窗口也无法执行操作了。</p>
</blockquote>
<ul>
<li><p>exec命令</p>
<p>exec命令，可以在运行中容器内直接执行任意命令，格式为：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker [container] <span class="built_in">exec</span> [-d|--detach] [--detach-keys[=[]]] [-i|--interactive] [--privileged] [-t|--tty] [-u|--user[=USER]] CONTAINER COMMAND [ARG...]</span><br></pre></td></tr></table></figure>

<p><code>-d,--detach</code>:在容器中后台执行命令</p>
<p><code>--datach-keys=&quot;&quot;</code>:指定将容器切回后台的按键</p>
<p><code>-e,--env=[]</code>:指定环境变量列表</p>
<p><code>-i,--interactive=true|false</code>:打开标准输入接受用户输入命令，默认值为false</p>
<p><code>--privileged=true|false</code>:是否给执行命令以最高权限，默认值为false</p>
<p><code>-t,--tty=true|false</code>:分配伪终端，默认值为false</p>
<p><code>-u,--user=&quot;&quot;</code>：执行命令的用户名或ID</p>
<p>示例：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker <span class="built_in">exec</span> -it 0dfbff61afc4 /bin/bash</span><br></pre></td></tr></table></figure></li>
</ul>
<h3 id="删除容器"><a href="#删除容器" class="headerlink" title="删除容器"></a>删除容器</h3><p>使用<code>docker [container] rm</code>命令删除处于终止或者退出状态的容器，命令格式为：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker [container] rm [-f|--force] [-l|--link] [-v|--volumes] CONTAINER [CONTAINER...]</span><br></pre></td></tr></table></figure>

<p><code>-f,--force=true|false</code>:是否强行终止并删除一个运行中的容器</p>
<p><code>-l.--link=true|false</code>：是否删除容器的连接，但保留容器</p>
<p><code>-v,--volumes=true|false</code>:是否删除容器挂载的数据卷</p>
<blockquote>
<p>通常情况下，<code>docker rm </code>命令只能删除已经处于终止或退出状态的容器，并不能删除处于运行状态的容器，附加<code>-f</code>可以直接删除运行中的容器。Docker会先发送SIGKILL信号给容器，终止其中的应用，之后强行删除。</p>
</blockquote>
<h3 id="导入和导出容器"><a href="#导入和导出容器" class="headerlink" title="导入和导出容器"></a>导入和导出容器</h3><ul>
<li><p>导出容器</p>
<p>导出容器就是，导出一个已经创建的容器到一个文件，不管此时这个容器是否处于运行状态。使用<code>docker [container] export</code>命令格式为:</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker [container] <span class="built_in">export</span> [-o|--output[=<span class="string">&quot;&quot;</span>]] CONTAINER</span><br></pre></td></tr></table></figure>

<p><code>-o</code>选项可以指定导出的tar文件名，也可以直接通过重定向来实现。</p>
<p>示例：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">$ docker ps -a </span><br><span class="line">CONTAINER ID   IMAGE     COMMAND       CREATED          STATUS                     PORTS     NAMES</span><br><span class="line">c4fd432c80f0   ubuntu    <span class="string">&quot;/bin/bash&quot;</span>   11 seconds ago   Exited (0) 6 seconds ago             wizardly_kepler</span><br><span class="line">$ docker <span class="built_in">export</span> -o test_for_run.tar c4fd432c80f0</span><br><span class="line">$ ls</span><br><span class="line">Dockerfile  client  docker-compose  dockergui  go_demo  server  test_for_run.tar</span><br><span class="line">$ docker <span class="built_in">export</span> c4fd432c80f0 &gt;test_for_stop.tar</span><br><span class="line">$ ls</span><br><span class="line">Dockerfile  client  docker-compose  dockergui  go_demo  server  test_for_run.tar  test_for_stop.tar</span><br></pre></td></tr></table></figure></li>
<li><p>导入容器</p>
<p>导出的文件使用<code>docker [container] import</code>命令导入变成镜像，命令格式为：</p>
<p><code>docker import [-c|--change[=[]]] [-m|--message[=MESSAGE]] file|URL|-[REPOSITORY[:TAG]]</code></p>
<p>  示例：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">$ docker import test_for_run.tar  <span class="built_in">test</span>/ubuntu:v1.0</span><br><span class="line">$ docker images</span><br><span class="line">REPOSITORY                   TAG            IMAGE ID       CREATED         SIZE</span><br><span class="line"><span class="built_in">test</span>/ubuntu                  v1.0           1c4787ec5f86   5 seconds ago   72.9MB</span><br></pre></td></tr></table></figure>

<blockquote>
<p>既可以使用<code>docker load</code>命令来导入镜像存储文件到本地镜像库，也可以使用<code>docker [container] import</code>命令来导入一个容器快照到本地镜像库。</p>
<p>两者的区别在于：<code>docker [container] import</code>命令导入快照文件将丢失所有的历史记录和元数据信息（即仅保存容器当时的快照状态），并且可以重新指定标签等元数据信息；而<code>docker load</code>命令导入镜像存储文件将保存完整记录，体积更大。</p>
</blockquote>
</li>
</ul>
<h3 id="查看容器"><a href="#查看容器" class="headerlink" title="查看容器"></a>查看容器</h3><ul>
<li><p>查看容器详情</p>
<p>查看容器详情命令使用<code>docker container inspect [OPTIONS] CONTAINER [CONTAINER...]</code></p>
<p>查看容器的具体信息，会以json格式返回包括容器ID、创建时间、路径、状态、镜像、配置等在内的各项信息。</p>
</li>
<li><p>查看容器内进程</p>
<p>查看容器内使用<code>docker [container] top [OPTIONS] CONTAINER [CONTAINER...]</code></p>
<p>这个命令类似于Linux系统中的top命令，会打印出容器内的进程信息，包括PID、用户、时间、命令等。</p>
<p>示例：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">$ docker top c4fd432c80f0</span><br><span class="line"> UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD</span><br><span class="line">root                975                 955                 1                   10:49               pts/0               00:00:00            /bin/bash</span><br></pre></td></tr></table></figure></li>
<li><p>查看统计信息</p>
<p>使用<code>docker [container] stats [OPTIONS] [CONTAINER...]</code>，会显示CPU、内存、存储、网络等使用情况的统计信息。</p>
<p>可以附加一下选项：</p>
<p><code>-a,-all</code>：输出所有容器统计信息，默认仅在运行中</p>
<p><code>-format string</code>：格式化输出信息</p>
<p><code>-no-stream</code>：不持续输出，默认会自动更新持续实时结果</p>
<p><code>-no-trunc</code>:不截断输出信息</p>
<p>示例：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">$ docker container stats c4fd432c80f0</span><br><span class="line">CONTAINER ID   NAME              CPU %     MEM USAGE / LIMIT     MEM %     NET I/O       BLOCK I/O   PIDS</span><br><span class="line">c4fd432c80f0   wizardly_kepler   0.00%     2.055MiB / 9.252GiB   0.02%     1.12kB / 0B   0B / 0B     1</span><br><span class="line">CONTAINER ID   NAME              CPU %     MEM USAGE / LIMIT     MEM %     NET I/O       BLOCK I/O   PIDS</span><br><span class="line">c4fd432c80f0   wizardly_kepler   0.00%     2.055MiB / 9.252GiB   0.02%     1.12kB / 0B   0B / 0B     1</span><br><span class="line">CONTAINER ID   NAME              CPU %     MEM USAGE / LIMIT     MEM %     NET I/O       BLOCK I/O   PIDS</span><br></pre></td></tr></table></figure></li>
</ul>
<h3 id="其他容器命令"><a href="#其他容器命令" class="headerlink" title="其他容器命令"></a>其他容器命令</h3><p>主要是Docker容器的cp、diff、port和update命令。</p>
<ul>
<li><p>复制文件</p>
<p><code>container cp</code>命令支持在容器和主机之间复制文件，命令格式为：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">docker [container] cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|-</span><br><span class="line">docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH</span><br></pre></td></tr></table></figure>

<p>可以附加以下参数:</p>
<p><code>-a,-archive</code>：打包模式，复制文件会带有原始的uid/gid信息</p>
<p><code>-L,-follow-link</code>：跟随软连接。当原原路径为软连接时，默认只复制链接信息，使用该选项会复制链接的目标内容。</p>
<p>示例：</p>
<p>将本地的路径client复制到容器4280de5741e1的/tmp路径下：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker container cp client 4280de5741e1:/tmp</span><br></pre></td></tr></table></figure>

<p>将容器4280de5741e1的tmp路径下client复制到本地/tmp下：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker container cp 4280de5741e1:/tmp client</span><br></pre></td></tr></table></figure></li>
<li><p>查看变更</p>
<p><code>docker diff</code>查看容器内文件系统的变更，命令格式为：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker [container] diff CONTAINER</span><br></pre></td></tr></table></figure>

<p>示例：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">$ docker container diff 4280de5741e1</span><br><span class="line">C /var</span><br><span class="line">C /var/<span class="built_in">log</span></span><br><span class="line">C /var/<span class="built_in">log</span>/apt</span><br><span class="line">C /var/<span class="built_in">log</span>/apt/eipp.log.xz</span><br><span class="line">C /var/<span class="built_in">log</span>/apt/history.log</span><br><span class="line">A /var/<span class="built_in">log</span>/apt/term.log</span><br><span class="line">C /var/<span class="built_in">log</span>/dpkg.log</span><br><span class="line">C /var/lib</span><br><span class="line">C /var/lib/apt</span><br><span class="line">C /var/lib/apt/extended_states</span><br><span class="line">C /var/lib/apt/lists</span><br><span class="line">A /var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_focal_main_binary-amd64_Packages.lz4</span><br></pre></td></tr></table></figure></li>
<li><p>查看端口映射</p>
<p><code>container port</code>命令可以查看容器的端口映射情况，命令格式为:</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker container port CONTAINER [PRIVATE_PORT[/PROTO]]</span><br></pre></td></tr></table></figure>

<p>示例：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ docker container port 4280de5741e1</span><br></pre></td></tr></table></figure></li>
<li><p>更新配置</p>
<p><code>container update</code>命令可以更新容器的一些运行时配置。主要是一些资源限制份额，命令格式为：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker [container] update [OPTIONS] CONTAINER [CONTAINER...]</span><br></pre></td></tr></table></figure>

<p>附加参数待补充。</p>
</li>
</ul>
<h2 id="Docker数据管理"><a href="#Docker数据管理" class="headerlink" title="Docker数据管理"></a>Docker数据管理</h2><p>容器中的管理数据主要有两种方式：</p>
<ul>
<li>数据卷（Data Volumes）：容器内数据直接映射到本地主机环境；</li>
<li>数据卷容器（Data Volume Containers）:使用特定容器维护数据卷。</li>
</ul>
<h3 id="数据卷"><a href="#数据卷" class="headerlink" title="数据卷"></a>数据卷</h3><p>数据卷（Data Volumes）是一个可供容器使用的特殊目录，它将主机操作系统目录直接映射容器，类似于Linux中的mount行为。</p>
<p>数据卷的特性：</p>
<ul>
<li>数据卷可以在容器之间共享和重用，容器间传递数据将变得高效与方便</li>
<li>对数据卷内数据的修改会立马生效，无论是容器内操作还是本地操作</li>
<li>对数据卷的更新不会影响镜像，解耦开应用和数据</li>
<li>卷会一直存在，直到没有容器使用，可以安全地卸载</li>
</ul>
<ol>
<li><p>创建数据卷</p>
<p>Docker提供了volume命令来管理数据卷。</p>
<p>示例：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">$ docker volume create -d <span class="built_in">local</span> <span class="built_in">test</span></span><br><span class="line"><span class="built_in">test</span></span><br><span class="line">$ sudo ls -l /var/lib/docker/volumes</span><br><span class="line">drwxr-xr-x 3 root root  4096 Dec 29 16:29 <span class="built_in">test</span></span><br></pre></td></tr></table></figure>

<p>除了<code>create</code>命令，还有<code>inspect</code>（查看详细信息）、<code>ls</code>（列出已有数据卷）、<code>prune</code>（清理无用数据卷）、<code>rm</code>（删除数据卷）等。</p>
<p>示例：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line">$ docker volume inspect <span class="built_in">test</span></span><br><span class="line">[</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="string">&quot;CreatedAt&quot;</span>: <span class="string">&quot;2020-12-29T16:29:09+08:00&quot;</span>,</span><br><span class="line">        <span class="string">&quot;Driver&quot;</span>: <span class="string">&quot;local&quot;</span>,</span><br><span class="line">        <span class="string">&quot;Labels&quot;</span>: &#123;&#125;,</span><br><span class="line">        <span class="string">&quot;Mountpoint&quot;</span>: <span class="string">&quot;/var/lib/docker/volumes/test/_data&quot;</span>,</span><br><span class="line">        <span class="string">&quot;Name&quot;</span>: <span class="string">&quot;test&quot;</span>,</span><br><span class="line">        <span class="string">&quot;Options&quot;</span>: &#123;&#125;,</span><br><span class="line">        <span class="string">&quot;Scope&quot;</span>: <span class="string">&quot;local&quot;</span></span><br><span class="line">    &#125;</span><br><span class="line">]</span><br><span class="line">$ docker volume ls</span><br><span class="line">DRIVER    VOLUME NAME</span><br><span class="line"><span class="built_in">local</span>     bc156d2f31b8291b9a0d923af592af55bbdd438c89d8d469d903247562ad141c</span><br><span class="line"><span class="built_in">local</span>     c228f67514546011e599380542a265f5439b5eaeaec720f2ab1bfc250ae79004</span><br><span class="line"><span class="built_in">local</span>     cbcdc10d6ade4978e215914d1df0f7cdc7f7ccf24f9b2bced4ce459c8e91625e</span><br><span class="line"><span class="built_in">local</span>     e9174cd1230749d09b5a00a1705dcfb69290f2ed61837a819ef88086cbe7336f</span><br><span class="line"><span class="built_in">local</span>     f652eafbc57b34d582206cc3b060f2d844f1ace72f5793b9c0ca8a62325f4f65</span><br><span class="line"><span class="built_in">local</span>     <span class="built_in">test</span></span><br><span class="line">$ docker volume prune</span><br><span class="line">WARNING! This will remove all <span class="built_in">local</span> volumes not used by at least one container.</span><br><span class="line">Are you sure you want to <span class="built_in">continue</span>? [y/N] y</span><br><span class="line">Deleted Volumes:</span><br><span class="line">bc156d2f31b8291b9a0d923af592af55bbdd438c89d8d469d903247562ad141c</span><br><span class="line">c228f67514546011e599380542a265f5439b5eaeaec720f2ab1bfc250ae79004</span><br><span class="line">cbcdc10d6ade4978e215914d1df0f7cdc7f7ccf24f9b2bced4ce459c8e91625e</span><br><span class="line">e9174cd1230749d09b5a00a1705dcfb69290f2ed61837a819ef88086cbe7336f</span><br><span class="line">f652eafbc57b34d582206cc3b060f2d844f1ace72f5793b9c0ca8a62325f4f65</span><br><span class="line"><span class="built_in">test</span></span><br><span class="line"></span><br><span class="line">Total reclaimed space: 61.19MB</span><br></pre></td></tr></table></figure></li>
<li><p>绑定数据卷</p>
<p>除了<code>volume</code>命令来管理数据卷外，还可以在创建容器时将主机本地的任意路径挂在到容器内作为数据卷，这种形式称为绑定数据卷。</p>
<p>在使用<code>docker [container] run</code>命令时，可以使用<code>-mount</code>选项来使用数据卷。</p>
<p><code>-mount</code>支持三种类型的数据卷，包括：</p>
<ul>
<li>volume：普通数据卷，映射到主机<code>/var/lib/docker/volume</code>路径下</li>
<li>bind：绑定数据卷，映射到主机指定路径下</li>
<li>tmpfs：临时数据卷，只存在于内存中</li>
</ul>
</li>
</ol>
<h3 id="数据数据卷"><a href="#数据数据卷" class="headerlink" title="数据数据卷"></a>数据数据卷</h3><p>如果需要在多个容器之间共享一些持续更新的数据，最简单的方式是使用数据卷容器。数据卷也是一个容器，但数据卷容器是专门提供数据卷给其他容器挂载的。</p>
<p>示例：</p>
<p>首先，先创建一个数据卷容器<code>dbdata</code>，并在其中创建一个数据卷挂载到<code>/dbdata</code>。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">$ docker run -it -v /dbdata --name dbdata ubuntu</span><br><span class="line">root@252f61efd7a6:/<span class="comment"># ls</span></span><br><span class="line">bin   dbdata  etc   lib    lib64   media  opt   root  sbin  sys  usr</span><br><span class="line">boot  dev     home  lib32  libx32  mnt    proc  run   srv   tmp  var</span><br><span class="line">root@252f61efd7a6:/<span class="comment"># cd /dbdata</span></span><br><span class="line">root@252f61efd7a6:/dbdata<span class="comment"># touch test</span></span><br><span class="line">root@252f61efd7a6:/dbdata<span class="comment"># ls</span></span><br><span class="line"><span class="built_in">test</span></span><br></pre></td></tr></table></figure>

<p>然后，可以在其他容器中使用<code>--volumes-from</code>来挂载<code>dbdata</code>容器中的数据卷，例如创建db1和db2两个容器 ，并从<code>dbdata</code>容器挂载数据卷：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">$ docker run -it --volumes-from dbdata --name db1 ubuntu</span><br><span class="line">$ docker run -it --volumes-from dbdata --name db2 ubuntu</span><br><span class="line">$ docker ps -a</span><br><span class="line">CONTAINER ID   IMAGE     COMMAND       CREATED          STATUS                      PORTS     NAMES</span><br><span class="line">dce1854c9cef   ubuntu    <span class="string">&quot;/bin/bash&quot;</span>   10 minutes ago   Exited (0) 9 minutes ago              db2</span><br><span class="line">b46d75dae642   ubuntu    <span class="string">&quot;/bin/bash&quot;</span>   10 minutes ago   Exited (0) 10 minutes ago             db1</span><br><span class="line">252f61efd7a6   ubuntu    <span class="string">&quot;/bin/bash&quot;</span>   16 minutes ago   Up 4 minutes                          dbdata</span><br><span class="line">$ docker container start  252f61efd7a6</span><br><span class="line">$ docker <span class="built_in">exec</span> -it b46d75dae642 /bin/bash</span><br><span class="line">root@b46d75dae642:/<span class="comment"># ls</span></span><br><span class="line">bin   dbdata  etc   lib    lib64   media  opt   root  sbin  sys  usr</span><br><span class="line">boot  dev     home  lib32  libx32  mnt    proc  run   srv   tmp  var</span><br><span class="line">root@b46d75dae642:/<span class="comment"># cd dbdata</span></span><br><span class="line">root@b46d75dae642:/dbdata<span class="comment"># ls</span></span><br><span class="line"><span class="built_in">test</span></span><br></pre></td></tr></table></figure>

<p>容器db1和db2都挂载到相同一个数据卷到相同的<code>dbdata</code>目录，三个容器任何一方在该目录下写入，其他容器都能看到。</p>
<p>可以多次使用<code>-volumes-from</code>参数来从多个容器挂载多个数据卷，还可以从其他已经挂载了容器卷的容器来挂载数据卷，示例：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ docker run -d --name db3 --volumes-from db1 training/postgres</span><br></pre></td></tr></table></figure>

<blockquote>
<p>使用<code>--volumes-from</code>参数挂载数据卷的容器自身并不需要保持在运行状态。</p>
</blockquote>
<p>如果删除了挂载的容器（包括dbdata、db1、db2），数据卷并不会被自动删除。如果要删除一个数据卷，必须在删除最后一个还挂在着它的容器时显示使用<code>docker rm -v</code>命令来指定并同时删除关联的容器。</p>
<h3 id="利用数据卷容器来迁移数据-不懂"><a href="#利用数据卷容器来迁移数据-不懂" class="headerlink" title="利用数据卷容器来迁移数据(不懂)"></a>利用数据卷容器来迁移数据(不懂)</h3><p>可以利用数据卷容器对其中的数据卷进行备份、恢复，以实现数据的迁移。</p>
<ol>
<li><p>备份</p>
<p><code>docker run --volumes-from dbdata -v </code></p>
</li>
</ol>
<h2 id="端口映射与容器互联（需要增加network连接）"><a href="#端口映射与容器互联（需要增加network连接）" class="headerlink" title="端口映射与容器互联（需要增加network连接）"></a>端口映射与容器互联（需要增加network连接）</h2><p><strong>多个容器之间相互访问对方的服务</strong></p>
<h3 id="端口映射实现容器访问"><a href="#端口映射实现容器访问" class="headerlink" title="端口映射实现容器访问"></a>端口映射实现容器访问</h3><ol>
<li><p>从外部访问容器应用</p>
<p>在启动容器的时候，如果不指定对应的参数，在容器外部是无法通过网络来访问容器内的网络应用和服务的。</p>
<p>当容器中运行一些网络应用，要让外部访问这些应用时，可通过<code>-P</code>或<code>-p</code>参数来指定端口映射。当使用<code>-P</code>标记时，Docker会随机映射一个49000~49900的端口到内部容器开放的网络端口，示例：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">$ docker run -d -P training/webapp python app.py</span><br><span class="line">$ docker ps -l</span><br><span class="line">CONTAINER ID   IMAGE             COMMAND           CREATED         STATUS         PORTS                     NAMES</span><br><span class="line">d9810c758aad   training/webapp   <span class="string">&quot;python app.py&quot;</span>   8 seconds ago   Up 7 seconds   0.0.0.0:49153-&gt;5000/tcp   busy_feynman</span><br></pre></td></tr></table></figure>

<p>通过<code>docker logs</code>命令查看应用的信息，需要打开<a target="_blank" rel="noopener" href="http://localhost:49153/%EF%BC%9A">http://localhost:49153/：</a></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">$ docker logs -f busy_feynman</span><br><span class="line"> * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)</span><br><span class="line">172.17.0.1 - - [29/Dec/2020 11:47:57] <span class="string">&quot;GET / HTTP/1.1&quot;</span> 200 -</span><br><span class="line">172.17.0.1 - - [29/Dec/2020 11:47:57] <span class="string">&quot;GET /favicon.ico HTTP/1.1&quot;</span> 404 -</span><br><span class="line">172.17.0.1 - - [29/Dec/2020 11:48:35] <span class="string">&quot;GET /favicon.ico HTTP/1.1&quot;</span> 404 -</span><br></pre></td></tr></table></figure>

<p>当使用<code>-p</code>时，需要指定要映射的端口，并且，在一个指定的端口上只可以绑定一个容器。命令的格式为：</p>
<p><code>IP:HostPort:ContainerPort | IP::ContainerPort | HostPort:ContainerPort </code></p>
</li>
<li><p>映射所有接口地址</p>
<p>使用<code>HostPort:ContainerPort</code>格式本地的5000端口映射到容器的5000端口，示例：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">$ docker run -d -p 5000:5000 training/webapp python app.py</span><br><span class="line">1690f9b6d20efd3a77ffd7e9d61a85ee5aa69b4622fc6a4a0a4aaa1b1ab439c4</span><br><span class="line">$ docker ps -l</span><br><span class="line">CONTAINER ID   IMAGE             COMMAND           CREATED         STATUS         PORTS                    NAMES</span><br><span class="line">1690f9b6d20e   training/webapp   <span class="string">&quot;python app.py&quot;</span>   3 seconds ago   Up 2 seconds   0.0.0.0:5000-&gt;5000/tcp   nice_diffie</span><br><span class="line">docker logs -f nice_diffie</span><br><span class="line"> * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)</span><br><span class="line">172.17.0.1 - - [29/Dec/2020 12:01:48] <span class="string">&quot;GET / HTTP/1.1&quot;</span> 200 -</span><br><span class="line">172.17.0.1 - - [29/Dec/2020 12:01:49] <span class="string">&quot;GET /favicon.ico HTTP/1.1&quot;</span> 404 -</span><br></pre></td></tr></table></figure>

<p>？？？此时默认会绑定本地所有接口上的所有地址，多次使用<code>-p</code>标记可以绑定多个端口，示例：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ docker run -d -p 5000:5000  -p 3000:80 training/webapp python app.py</span><br></pre></td></tr></table></figure></li>
<li><p>映射到指定地址的指定端口</p>
<p>使用<code>IP:HostPort:ContainerPort</code>格式指定映射使用一个特定地址，例如`localhost地址127.0.0.1:</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ docker run -d -p 127.0.0.1:5000:5000 training/webapp python app.py</span><br></pre></td></tr></table></figure></li>
<li><p>映射到指定地址的任意端口</p>
<p>使用<code>IP::ContainerPort</code>绑定localhost的任意端口到容器的5000端口，本地主机会自动分配一个端口：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ docker run -d -p 127.0.0.1::5000 training/webapp python app.py</span><br></pre></td></tr></table></figure>

<p>还可以使用udp标记指定udp端口：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ docker run -d -p 127.0.0.1:5000:5000/udp taining/webapp python app.py</span><br></pre></td></tr></table></figure></li>
<li><p>查看映射端口配置</p>
<p>使用<code>docker port</code>来查看当前映射的端口配置，也可以查看绑定的地址：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ docker port b02a9ae09404 5000</span><br><span class="line">0.0.0.0:49154</span><br></pre></td></tr></table></figure>

<blockquote>
<p>容器有自己的内部网络和IP地址，使用<code>docker [container] inspect ID</code>可以获取容器的具体信息。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">$ docker container inspect b02a9ae09404</span><br><span class="line"><span class="string">&quot;Ports&quot;</span>: &#123;</span><br><span class="line">             <span class="string">&quot;5000/tcp&quot;</span>: [</span><br><span class="line">                 &#123;</span><br><span class="line">                     <span class="string">&quot;HostIp&quot;</span>: <span class="string">&quot;0.0.0.0&quot;</span>,</span><br><span class="line">                     <span class="string">&quot;HostPort&quot;</span>: <span class="string">&quot;49154&quot;</span></span><br><span class="line">                 &#125;</span><br><span class="line">             ]</span><br><span class="line">         &#125;,</span><br></pre></td></tr></table></figure>

</blockquote>
</li>
</ol>
<h3 id="互联机制实现便捷互访"><a href="#互联机制实现便捷互访" class="headerlink" title="互联机制实现便捷互访"></a>互联机制实现便捷互访</h3><p>容器的<strong>互联</strong> （linking）是一种让多个容器中的应用进行快速交互的方式。它会在源和接收容器之间创建连接关系，接收容器可以通过容器名快速访问到源容器，而不用指定具体的IP地址。</p>
<ol>
<li><p>自定义容器命名</p>
<p>连接系统依据容器的名称来执行。首先需要自定义一个好记的容器命名，虽然创建容器时，系统默认会分配一个名字，但自定义命名容器有两个好处：</p>
<ul>
<li>自定义的命名，比较好记，一目了然</li>
<li>当要连接其他容器时候（即使重启），也可以使用容器名而不用改变</li>
</ul>
</li>
</ol>
<p>使用<code>--name</code>标记可以为容器自定义命名：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">$ docker run -d -P --name web training/webapp python app.py</span><br><span class="line">32d3bd81f939d49eb4d76105d96fa139c68fa9a8e6069bd07e6b69fcddb3e316</span><br><span class="line">$ docker ps</span><br><span class="line">CONTAINER ID   IMAGE             COMMAND           CREATED          STATUS          PORTS                     NAMES</span><br><span class="line">32d3bd81f939   training/webapp   <span class="string">&quot;python app.py&quot;</span>   16 seconds ago   Up 15 seconds   0.0.0.0:49155-&gt;5000/tcp   web</span><br></pre></td></tr></table></figure>

<p>也可以使用<code>docker [container] inspect </code>来查看容器的名字，示例：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ docker container inspect  -f <span class="string">&quot;&#123;&#123;.Name&#125;&#125;&quot;</span> 32d3bd81f939</span><br><span class="line">/web</span><br></pre></td></tr></table></figure>

<blockquote>
<p>容器的名字是唯一的。如果已经命名了一个叫web的容器，当再要使用web这个名称时，需要先用<code>docker rm</code>命令删除之前创建的同名容器。</p>
</blockquote>
<ol start="2">
<li><p>容器互联</p>
<p>使用<code>--link</code>参数可以让容器之间安全地进行交互，命令格式为：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">--link name:<span class="built_in">alias</span></span><br></pre></td></tr></table></figure>

<p><code>name</code>是要链接的容器的名称，<code>alias</code>是别名。</p>
<p>示例：</p>
<p>先创建一个新的数据库容器：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ docker run -d --name db training/postgres</span><br><span class="line">383c54976fe4d5e480c3f3b61e33d129c8acee59aca2e6e516ab33ff94d36632</span><br></pre></td></tr></table></figure>

<p>删除之前创建的web容器：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ docker rm -f web</span><br><span class="line">web</span><br></pre></td></tr></table></figure>

<p>创建新的web容器，并连接到db容器：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ docker run -d -P --name web --link db:db training/webapp python app.py</span><br><span class="line">8dbe69b98f31b3f079cf9a8a3c08a0e36d50e44f8083334379a0079601389702</span><br></pre></td></tr></table></figure>

<p>此时，db容器和web容器建立互联关系。</p>
<p>使用<code>docker ps</code>命令查看容器的连接：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">$ docker ps</span><br><span class="line">CONTAINER ID   IMAGE               COMMAND                  CREATED          STATUS          PORTS                     NAMES</span><br><span class="line">302d2742f841   training/webapp     <span class="string">&quot;python app.py&quot;</span>          10 minutes ago   Up 10 minutes   0.0.0.0:49157-&gt;5000/tcp   web</span><br><span class="line">dae047afc18a   training/postgres   <span class="string">&quot;su postgres -c &#x27;/us…&quot;</span>   12 minutes ago   Up 12 minutes   5432/tcp                  db</span><br></pre></td></tr></table></figure>

<p>？？？未实现？？？</p>
<p>Docker相当于在两个互联的容器之间创建一个虚拟通道，而且不用映射它们的端口到宿主主机上。在启动db容器时并没有使用-p或者-P标记，从而避免了暴露数据库服务端口到外部网络上。</p>
<p>Docker通过两种方式为容器公开连接信息：</p>
<ul>
<li>更新环境变量</li>
<li>更新<code>/etc/hosts</code>文件</li>
</ul>
<p>使用env命令来查看web容器的环境变量，示例：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">$ docker run --rm --name web2 --link db:db training/webapp env</span><br><span class="line">PATH=/usr/<span class="built_in">local</span>/sbin:/usr/<span class="built_in">local</span>/bin:/usr/sbin:/usr/bin:/sbin:/bin</span><br><span class="line">HOSTNAME=8fea1e9d41ff</span><br><span class="line">DB_PORT=tcp://172.17.0.2:5432</span><br><span class="line">DB_PORT_5432_TCP=tcp://172.17.0.2:5432</span><br><span class="line">DB_PORT_5432_TCP_ADDR=172.17.0.2</span><br><span class="line">DB_PORT_5432_TCP_PORT=5432</span><br><span class="line">DB_PORT_5432_TCP_PROTO=tcp</span><br><span class="line">DB_NAME=/web2/db</span><br><span class="line">DB_ENV_PG_VERSION=9.3</span><br><span class="line">HOME=/root</span><br></pre></td></tr></table></figure>

<p>Docker还添加host信息到父容器的<code>/etc/hosts</code>的文件，示例：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">$ docker run -t -i --rm --link db:db training/webapp /bin/bash</span><br><span class="line">root@dfe7c49be63b:/opt/webapp<span class="comment"># cat /etc/hosts</span></span><br><span class="line">127.0.0.1       localhost</span><br><span class="line">::1     localhost ip6-localhost ip6-loopback</span><br><span class="line">fe00::0 ip6-localnet</span><br><span class="line">ff00::0 ip6-mcastprefix</span><br><span class="line">ff02::1 ip6-allnodes</span><br><span class="line">ff02::2 ip6-allrouters</span><br><span class="line">172.17.0.2      db dae047afc18a</span><br><span class="line">172.17.0.4      dfe7c49be63b</span><br></pre></td></tr></table></figure>

<p>在web容器中安装ping命令来测试跟db容器的连通:</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">$ docker run -t -i --rm --link db:db training/webapp /bin/bash</span><br><span class="line">root@abc00affd5ce:/opt/webapp<span class="comment"># apt-get install -yqq inetutils-ping</span></span><br><span class="line">root@abc00affd5ce:/opt/webapp<span class="comment"># ping db</span></span><br><span class="line">PING db (172.17.0.2): 56 data bytes</span><br><span class="line">64 bytes from 172.17.0.2: icmp_seq=0 ttl=64 time=0.134 ms</span><br><span class="line">64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.091 ms</span><br><span class="line">64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.086 ms</span><br><span class="line">64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.112 ms</span><br><span class="line">64 bytes from 172.17.0.2: icmp_seq=4 ttl=64 time=0.071 ms</span><br><span class="line">64 bytes from 172.17.0.2: icmp_seq=5 ttl=64 time=0.108 ms</span><br><span class="line">64 bytes from 172.17.0.2: icmp_seq=6 ttl=64 time=0.083 ms</span><br><span class="line">64 bytes from 172.17.0.2: icmp_seq=7 ttl=64 time=0.133 ms</span><br><span class="line">^C--- db ping statistics ---</span><br><span class="line">8 packets transmitted, 8 packets received, 0% packet loss</span><br><span class="line">round-trip min/avg/max/stddev = 0.071/0.102/0.134/0.000 ms</span><br></pre></td></tr></table></figure></li>
</ol>
<h2 id="使用Dockerfile创建镜像"><a href="#使用Dockerfile创建镜像" class="headerlink" title="使用Dockerfile创建镜像"></a>使用Dockerfile创建镜像</h2><h3 id="基本结构"><a href="#基本结构" class="headerlink" title="基本结构"></a>基本结构</h3><p>Dockerfile由一行行命令语句组成，并支持以<code>#</code>为开头的注释行</p>
<p>Dockerfile主体由四部分组成：基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令。</p>
<p>示例：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># escape=\ (backslash)</span></span><br><span class="line"><span class="comment"># This dockerfile uses the ubuntu:xeniel image</span></span><br><span class="line"><span class="comment"># VERSION 2 - EDITION 1</span></span><br><span class="line"><span class="comment"># Author: docker_user</span></span><br><span class="line"><span class="comment"># Command format: Instruction [arguments / command] ..</span></span><br><span class="line"><span class="comment"># Base image to use, this must be set as the first line</span></span><br><span class="line">FROM ubuntu:xeniel</span><br><span class="line"><span class="comment"># Maintainer: docker_user &lt;docker_user at email.com&gt; (@docker_user)</span></span><br><span class="line">LABEL maintainer docker_user&lt;docker_user@email.com&gt;</span><br><span class="line"><span class="comment"># Commands to update the image</span></span><br><span class="line">RUN <span class="built_in">echo</span> <span class="string">&quot;deb https://archive.ubuntu.com/ubuntu/ xeniel main universe&quot;</span> &gt;&gt; /etc/apt/sources.list</span><br><span class="line">RUN apt-get update &amp;&amp; apt-get install -y nginx</span><br><span class="line">RUN <span class="built_in">echo</span> <span class="string">&quot;\ndaemon off;&quot;</span> &gt;&gt; /etc/nginx/nginx.conf</span><br><span class="line"><span class="comment"># Commands when creating a new container</span></span><br><span class="line">CMD /usr/sbin/nginx</span><br></pre></td></tr></table></figure>

<h3 id="配置指令"><a href="#配置指令" class="headerlink" title="配置指令"></a>配置指令</h3><ol>
<li><p>ARG</p>
<p>定义创建镜像过程中使用的变量，命令格式为<code>ARG &lt;name&gt; [=&lt;default value]</code>。</p>
<p>在执行<code>docker build</code>时，可通过<code>-bulid-arg[=]</code>来为变量赋值。镜像编译成功后，ARG指定的变量将不再存在。</p>
<p>Docker内置了一些无须声明就可以直接使用的镜像创建变量。<code>HTTP_PROXY、HTTPS_PROXY、FTP_PROXY、NO_PROXY</code>。</p>
</li>
<li><p>FROM</p>
<p>指定所创建镜像的基础镜像，命令格式为<code>FROM &lt;image&gt; [AS &lt;name&gt;]</code>或<code>FROM &lt;image&gt;:&lt;tag&gt; [AS &lt;name&gt;]</code>或<code>FROM &lt;image&gt;@&lt;digest&gt; [AS &lt;name&gt;]</code>。</p>
<p>任何Dockefile中第一条指令必须为<code>FROM</code>指令。如果在同一个Dockefile文件中创建多个镜像时，可以使用多个<code>FROM</code>指令。</p>
<blockquote>
<p>为了保证镜像精简，可以选择体积较小的镜像如<code>Alpine</code>或<code>Debian</code>作为基础镜像。</p>
</blockquote>
</li>
</ol>
<p>​       示例：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">ARG VERSION=9.3</span><br><span class="line">FROM debian:<span class="variable">$&#123;VERSION&#125;</span></span><br></pre></td></tr></table></figure>

<ol start="3">
<li><p>LABEL</p>
<p>LABEL指令可以为生成的镜像添加元数据标签信息。这些信息可以用来辅助过滤出特定镜像。命令格式为<code>LABEL &lt;key&gt;=&lt;value&gt; &lt;key&gt;=&lt;value&gt; &lt;key&gt;=&lt;value&gt; ...</code>。</p>
<p>示例：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">LABEL version=<span class="string">&quot;1.0.0-rc3&quot;</span></span><br><span class="line">LABEL author=<span class="string">&quot;yeasy@github&quot;</span> date=<span class="string">&quot;2020-01-01&quot;</span></span><br><span class="line">LABEL description=<span class="string">&quot;This text illustrates that label-values can span multiple lines.&quot;</span></span><br></pre></td></tr></table></figure></li>
<li><p>EXPOSE</p>
<p><strong>声明</strong>镜像内服务监听的端口，命令格式为<code>EXPOSE &lt;port&gt; [&lt;port&gt;/&lt;protocol&gt;...]</code>。仅仅是声明而已，并不能自动完成端口映射。</p>
<p>示例：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">EXPOSE 22 80 8443</span><br></pre></td></tr></table></figure></li>
<li><p>ENV</p>
<p>指定环境变量，在镜像生成过程中会被后续RUN指令使用，在镜像启动的容器中也会存在，命令格式为：</p>
<p><code>ENV &lt;key&gt; &lt;value&gt;</code>或<code>ENV &lt;key&gt;=&lt;value&gt;...</code>。</p>
<p>示例：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">ENV APP_VERSION=1.0.0</span><br><span class="line">ENV APP_HOME=/usr/<span class="built_in">local</span>/app</span><br><span class="line">ENV PATH <span class="variable">$PATH</span>:/usr/<span class="built_in">local</span>/bin</span><br></pre></td></tr></table></figure>

<blockquote>
<p>当一条<code>ENV</code>指令中同时为多个变量赋值并且值也是从环境变量读取时，会为变量都赋值后再更新。</p>
<p><code>ENV key1=value2</code></p>
<p><code>ENV key1=value1 key2=$&#123;key1&#125;</code></p>
<p>最终结果为<code>key1=value1 key2=value2</code></p>
</blockquote>
</li>
<li><p>ENTRYPOINT</p>
<p>指定镜像的默认入口命令，该命令会在启动容器时作为根命令执行，所有传入值作为该命令的参数，命令格式为：</p>
<ul>
<li><code>ENTRYPOINT [&quot;executable&quot;,&quot;param1&quot;,&quot;param2&quot;]: exec</code>调用执行</li>
<li><code>ENTRYPOINT command parma1 param2: shell</code>中执行<br>此时，CMD命令指定值将作为根命令的参数。</li>
</ul>
<blockquote>
<p>当指定多个ENTRYPOINT时，只有最后一个起效。</p>
</blockquote>
</li>
<li><p>VOLUME</p>
<p>创建一个数据卷挂载点，命令格式为<code>VOLUME [&quot;/data&quot;]</code>。</p>
<p>运行容器时可以从本地或其他容器挂在数据卷，一般用来存放数据库和需要保持的数据等。</p>
</li>
<li><p>USER</p>
<p>指定运行容器时的用户名或UID，后续的<code>RUN</code>等指令也会使用指定的用户身份，命令格式为:<code>USER daemon</code>。</p>
<blockquote>
<p>当服务不需要管理员权限时，可以通过该命令指定运行用户，并且可以在Dockerfile中创建所需要的用户。</p>
<p>要临时获取管理员权限可以使用<code>gosu</code>命令。</p>
</blockquote>
</li>
</ol>
<p>​       示例：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">RUN groupadd -r postfres &amp;&amp; useradd --no-log-init -r -g postgres postgres</span><br></pre></td></tr></table></figure>

<ol start="9">
<li><p>WORKDIR</p>
<p>为后续的<code>RUN</code>、<code>CMD</code>、<code>ENTRPOINT</code>指令配置工作目录，命令格式为：<code>WORKDIR /path/to/workdir</code>。</p>
<blockquote>
<p>可以使用多个<code>WORKDIR</code>指令，后续命令如果是相对路径，则会基于之间命令指定的路径。</p>
<p>因此，为了避免出错，推荐<code>WORKDIR</code>命令中只使用<strong>绝对路径</strong>。</p>
</blockquote>
</li>
<li><p>ONBUILD</p>
<p>指定当基于所生成镜像创建子镜像时，自动执行的操作指令，命令格式为：<code>ONBUILD [INSTRUCTION]</code>。</p>
<p>示例：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Dockerfile for ParentImage</span></span><br><span class="line">[...]</span><br><span class="line">ONBUILD ADD ./app/src</span><br><span class="line">ONBUILD RUN /usr/<span class="built_in">local</span>/bin/python-build --dir /app/src</span><br><span class="line">[...]</span><br></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Dockerfile for ChildImage</span></span><br><span class="line">FROM ParentImage</span><br></pre></td></tr></table></figure>

<p>等价于:</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Automatically run the following when building ChildImage</span></span><br><span class="line">ADD ./app/src</span><br><span class="line">RUN /usr/<span class="built_in">local</span>/bin/python-build --dir /app/src</span><br><span class="line">...</span><br></pre></td></tr></table></figure>

<blockquote>
<p>由于<code>ONBUILD</code>指令是隐式执行的，因此建议在它的镜像标签中进行标注，例如<code>ruby:2.1-onbuild</code>。</p>
<p><code>ONBUILD</code>指令在创建专门用于自动编译、检查等操作的基础镜像时，十分有用。</p>
</blockquote>
</li>
<li><p>STOPSIGNAL</p>
<p>指定所创建镜像启动的容器接收退出的信号值，<code>STOPSIGNAL signal</code>。</p>
</li>
<li><p>HEALTHCHECK</p>
<p>配置所启动容器如何进行健康检查（如何判断是否健康），命令格式为：</p>
<ul>
<li><p><code>HEALTHCHECK [OPTIONS] CMD command</code>: 根据所执行命令返回值是否为0来判断</p>
</li>
<li><p><code>HEALTHCHECK NONE</code>: 禁止基础镜像中的健康检查。</p>
</li>
</ul>
</li>
</ol>
<p>​      OPTION支持如下参数:</p>
<p>​       -interval=DURATION (default: 30s)    过多久检查一次</p>
<p>​      -timeout=DURATION (default: 30s)   每次检查等待结果的超时</p>
<p>​      -retries=N (default: 3)    如果失败了，重试几次才最终确定失败。</p>
<ol start="13">
<li><p>SHELL</p>
<p>指定其他命令使用<code>shell</code>时默认的<code>shell</code>类型：</p>
<p><code>SHELL [&quot;executable&quot;,&quot;parameters&quot;]</code></p>
<p>默认值为： <code>[&quot;/bin/sh&quot;,&quot;-c&quot;]</code></p>
</li>
</ol>
<h3 id="操作指令"><a href="#操作指令" class="headerlink" title="操作指令"></a>操作指令</h3><ol>
<li><p>RUN</p>
<p>运行指定的命令，命令格式为<code>RUN &lt;command&gt;</code>或<code>RUN [&quot;executable&quot;,&quot;param1&quot;,&quot;param2&quot;]</code>。</p>
<p>第二条指令会被解析为JSON数组，因此必须用<strong>双引号</strong>。第二条指令使用<code>exec</code>执行，不会启动<code>shell</code>环境。</p>
<p>第一条指令默认在<code>shell</code>终端中运行命令，即<code>/bin/sh -c</code>。</p>
<p>指定使用其他终端类型可以通过第二条指令实现，如<code>RUN [&quot;/bin/bash&quot;,&quot;-c&quot;.&quot;echo hello&quot;]</code>。</p>
<p>每条<code>RUN</code>指令将在当前镜像基础上执行指定命令，并提交为新的镜像层。<strong>若命令较长时，可以使用<code>\</code>来换行。</strong></p>
<p>示例：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">RUN apt-get update \</span><br><span class="line">&amp;&amp; apt-get install -y libsnappy-dev zliblg-dev libbz2-dev \</span><br><span class="line">&amp;&amp; rm -rf /var/cache/apt \</span><br><span class="line">&amp;&amp; rm -rf /var/lib/apt/lists/*</span><br></pre></td></tr></table></figure></li>
<li><p>CMD</p>
<p><code>CMD</code>命令用来指定启动容器时默认执行的命令，命令格式为：</p>
<ul>
<li><code>CMD [&quot;executable&quot;,&quot;param1&quot;,&quot;param2&quot;]</code>    相当于执行<code>executable param1 param2</code>，<strong>推荐方式</strong>。</li>
<li><code>CMD command param1 param2</code>   在默认的<code>Shell</code>中执行，提供给需要交互的应用</li>
<li><code>CMD [&quot;param1&quot;,&quot;param2&quot;]</code>   提供给<code>ENTRYPOINT</code>的默认参数</li>
</ul>
</li>
</ol>
<p>​       每个Dockfile只能有一条<code>CMD</code>命令。如果指定了多条，则只有最后一条被执行。</p>
<ol start="3">
<li><p>ADD</p>
<p>添加内容到镜像，命令格式为: <code>ADD &lt;src&gt; &lt;dest&gt;</code>。</p>
<p>该命令将复制指定的<code>&lt;src&gt;</code>路径下的内容到容器中的<code>&lt;dest&gt;</code>路径下。</p>
<p>其中，<code>&lt;src&gt;</code>可以是：</p>
<ul>
<li>Dockerfile所在目录的一个相对路径（文件或目录）</li>
<li>一个URL</li>
<li>一个tar文件（自动解压为目录）</li>
</ul>
<p> <code>&lt;dest&gt;</code>可以是：</p>
<ul>
<li>镜像内绝对路径</li>
<li>相对于工作目录（WORKDIR）的相对路径</li>
</ul>
</li>
</ol>
<p>​        路径支持正则格式，示例：<br>​         <code>ADD *.c /code/</code></p>
<ol start="4">
<li><p>COPY</p>
<p>复制内容到镜像，命令格式为:<code>COPY &lt;src&gt; &lt;dest&gt;</code>。</p>
<p>复制本地主机的<code>&lt;src&gt;</code>（为Dockerfile所在目录的相对路径，文件或目录）下内容到镜像的<code>&lt;dest&gt;</code>。<code>&lt;dest&gt;</code>不存在时会自动创建。</p>
<blockquote>
<p>COPY与ADD指令功能相似，当使用本地目录为源目录时，推荐使用COPY</p>
</blockquote>
</li>
</ol>
<h3 id="创建镜像-1"><a href="#创建镜像-1" class="headerlink" title="创建镜像"></a>创建镜像</h3><p>编写完Dockerfile之后，通过<code>docker [image] build</code>命令来创建镜像，命令格式为：</p>
<p><code>docker build [OPTIONS] PATH | URL |-</code></p>
<p>该命令读取指定路径<code>PATH</code>下的Dockerfile，并将该路径下所有数据作为上下文（Context）发送到Docker服务端。Docker服务端在校验Dockerfile格式通过后，逐条执行其中的定义的指令，碰到<code>ADD、COPY和RUN</code>指令会生成一层新的镜像。如果创建成功，则返回最终镜像的ID。</p>

      
    </div>
    <footer class="article-footer">
      <a data-url="http://example.com/2021/10/13/docker/" data-id="ckuphbppy0000poubhbvt2yg5" class="article-share-link">Share</a>
      
      
    </footer>
  </div>
  
    
<nav id="article-nav">
  
    <a href="/2021/10/13/2021%E5%B9%B4%E6%83%B3%E5%AE%8C%E6%88%90%E7%9A%84%E4%BA%8B/" id="article-nav-newer" class="article-nav-link-wrap">
      <strong class="article-nav-caption">Newer</strong>
      <div class="article-nav-title">
        
          (no title)
        
      </div>
    </a>
  
  
</nav>

  
</article>

</section>
        
          <aside id="sidebar">
  
    

  
    

  
    
  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Archives</h3>
    <div class="widget">
      <ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/archives/2021/10/">October 2021</a></li></ul>
    </div>
  </div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Recent Posts</h3>
    <div class="widget">
      <ul>
        
          <li>
            <a href="/2021/10/13/2021%E5%B9%B4%E6%83%B3%E5%AE%8C%E6%88%90%E7%9A%84%E4%BA%8B/">(no title)</a>
          </li>
        
          <li>
            <a href="/2021/10/13/docker/">(no title)</a>
          </li>
        
      </ul>
    </div>
  </div>

  
</aside>
        
      </div>
      <footer id="footer">
  
  <div class="outer">
    <div id="footer-info" class="inner">
      &copy; 2021 John Doe<br>
      Powered by <a href="http://hexo.io/" target="_blank">Hexo</a>
    </div>
  </div>
</footer>
    </div>
    <nav id="mobile-nav">
  
    <a href="/" class="mobile-nav-link">Home</a>
  
    <a href="/archives" class="mobile-nav-link">Archives</a>
  
</nav>
    

<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>


  
<link rel="stylesheet" href="/fancybox/jquery.fancybox.css">

  
<script src="/fancybox/jquery.fancybox.pack.js"></script>




<script src="/js/script.js"></script>




  </div>
</body>
</html>